#include "mod_gui.h"
#include "z_memory.h"
#include "data.h"
#include "string.h"
#include "stdio.h"
#include "dev.h"
#include "platform.h"

#define GUI_QUEUE_NUM 4

enum GuiMsgId{
    GUI_MSG_ID_IDLE = 0,
    GUI_MSG_ID_WAIT,
    GUI_MSG_ID_CHARGE,
    GUI_MSG_ID_UPDATE_CHARGE,
    GUI_MSG_ID_SETTLE,
    GUI_MSG_ID_ALARM,
    GUI_MSG_ID_NET,
};

struct GuiMsgNetState{
    uint8_t state;
};
struct GuiMsgChargeInfo{
    uint32_t kwh;
    uint32_t sec;
};
struct GuiMsgSettleInfo{
    uint32_t kwh;
    uint32_t sec;
    uint32_t cost;
};
struct GuiMsgAlarmInfo{
    char_t *code;
};
union GuiMsgInfo{
    struct GuiMsgNetState net;
    struct GuiMsgChargeInfo charge;
    struct GuiMsgSettleInfo settle;
    struct GuiMsgAlarmInfo alarm;
};

struct GuiQueueMsg{
    uint8_t msgid;
    uint8_t gunid;
    union GuiMsgInfo info;
};



static os_queue_t gui_queue;


void gui_show_init(uint8_t gun_id){

}
void gui_show_card_select(uint8_t select_id){

}
void gui_show_reswip_card(uint8_t cnt){

}
void gui_show_idle(uint8_t gun_id){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_IDLE;
    msg.gunid = gun_id;
    os_queue_send(gui_queue, &msg);
}
void gui_show_wait_gunin(uint8_t gun_id){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_WAIT;
    msg.gunid = gun_id;
    os_queue_send(gui_queue, &msg);
}
void gui_show_wait_charge(uint8_t cnt){

}
void gui_show_start_charging_fail(uint8_t gun_id, uint32_t cnt, char_t *reasion){

}
void gui_show_charge(uint8_t gun_id){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_CHARGE;
    msg.gunid = gun_id;
    os_queue_send(gui_queue, &msg);
}

void gui_update_charge(uint8_t gun_id, uint32_t kwh, uint32_t sec){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_UPDATE_CHARGE;
    msg.gunid = gun_id;
    msg.info.charge.kwh = kwh;
    msg.info.charge.sec = sec;
    os_queue_send(gui_queue, &msg);
}
void gui_show_charge_end(uint8_t gun_id, uint32_t kwh, uint32_t sec, char_t *reasion){

}
void gui_show_settle(uint8_t gun_id, int32_t tkwh, int32_t tsec, int32_t tcost, int32_t cnt){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_SETTLE;
    msg.gunid = gun_id;
    msg.info.settle.kwh = tkwh;
    msg.info.settle.sec = tsec;
    msg.info.settle.cost = tcost;
    os_queue_send(gui_queue, &msg);
}
void gui_show_alarm(uint8_t gun_id, char_t *code, char_t *desc){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_ALARM;
    msg.gunid = gun_id;
    msg.info.alarm.code = code;
    os_queue_send(gui_queue, &msg);    
}
void gui_show_net_state_online(void){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_NET;
    msg.info.net.state = 1;
    os_queue_send(gui_queue, &msg);

}
void gui_show_net_state_offline(void){
    struct GuiQueueMsg msg={0};
    msg.msgid = GUI_MSG_ID_NET;
    msg.info.net.state = 0;
    os_queue_send(gui_queue, &msg);
}
void gui_sync_time(void){

}

void gui_set_test_flag(uint8_t state){

}

static void lcd_show_idle(struct GuiQueueMsg *msg){
    char_t dev_id[20]={0};
    data_getstr("devid", dev_id, sizeof(dev_id));
    
    char_t buf[50]={0};
    data_getstr("qrcode", buf, sizeof(buf));
    strcat(buf, dev_id);
    char_t gun_str[10]={0};
    sprintf(gun_str, "%02d", msg->gunid);
    strcat(buf, gun_str);    
    
    gui_lcd_show_qrcode(buf);
}
static void lcd_show_wait_gunin(struct GuiQueueMsg *msg){    
    gui_lcd_show_idle();
}
static void lcd_show_charge(struct GuiQueueMsg *msg){
   gui_lcd_show_charge(); 
}
static void lcd_update_charge(struct GuiQueueMsg *msg){
    uint32_t vol = dev_get_vol(msg->gunid);
    uint32_t currt = dev_get_need_currt(msg->gunid);
    gui_lcd_update_charge(vol,currt,msg->info.charge.kwh,msg->info.charge.sec/60);
}
static void lcd_show_settle(struct GuiQueueMsg *msg){
     gui_lcd_show_settle(msg->info.settle.kwh, msg->info.settle.sec/60, msg->info.settle.cost);
}
static void lcd_show_alarm(struct GuiQueueMsg *msg){
    
     gui_lcd_show_alarm(msg->info.alarm.code);
}
static void lcd_show_net_state(struct GuiQueueMsg *msg){    
     gui_lcd_show_net(msg->info.net.state);
}

struct GuiMsgDeal{
    uint8_t msgid;
    void (*deal)(struct GuiQueueMsg *msg);
};

static const struct GuiMsgDeal g_guiMsgDeal[]={
    {GUI_MSG_ID_IDLE, lcd_show_idle},
    {GUI_MSG_ID_WAIT, lcd_show_wait_gunin},
    {GUI_MSG_ID_CHARGE, lcd_show_charge},
    {GUI_MSG_ID_UPDATE_CHARGE, lcd_update_charge},
    {GUI_MSG_ID_SETTLE, lcd_show_settle},
    {GUI_MSG_ID_ALARM, lcd_show_alarm},
    {GUI_MSG_ID_NET, lcd_show_net_state},
    
};

static void gui_poll(void){
    struct GuiQueueMsg msg;
    if (os_queue_read(gui_queue, &msg) != pdPASS) {
        return;
    }
    for(uint32_t i = 0; i< sizeof(g_guiMsgDeal)/sizeof(struct GuiMsgDeal); i++){
        if(g_guiMsgDeal[i].msgid == msg.msgid){
            g_guiMsgDeal[i].deal(&msg);
        }
    }
    
}
static void gui_task(void *para){
    uint32_t cnt = 0;
    while(1){
        gui_poll();
        if (cnt % 20 == 0){
            char_t time[20] = {0};
            rtc_get_currt_time_format(time, sizeof(time));
            gui_lcd_show_time(time);
        }
        cnt++;
        os_msleep(50);       
    }
}
 
int32_t gui_init(void){
    gui_lcd_init();
    char_t devid[20]={0};
    data_getstr("devid", devid, sizeof(devid));
    gui_lcd_show_bar(devid);
    gui_queue = os_queue_create(GUI_QUEUE_NUM, sizeof(struct GuiQueueMsg));
    if (gui_queue == NULL){
        return -1;
    }
    os_pthread_t gui_thread;
    
    if (os_pthread_create("gui", &gui_thread, gui_task, NULL,  OS_TASK_PRIO_LOW, OS_STACK_SIZE_SUPER_LARGE) != 0){
        return -1;
    } 
    return 0;
}
